<?php
/**
 * This class takes uri and filter controller,
 * module and action and validate them.
 * @author snc
 *
 */
class ControllerDispatcher{
	private $uriArray;
	private $actionPrefix = "snc";
	private $controllerPostfix = "Controller";
	private $moduleIndex=0;
	private $controllerIndex=1;
	private $actionIndex=2;
	private $isFromAdmin = false;
	private $defaultModule ="home";
	private $defaultController ="Index";
	private $defaultAction ="Index";
	private $controllerFile;
	public $viewFile;
	
	/**
	 * constructor	 
	 * @param $uri
	 */
	function __construct($uri){
		//cut off GET-part in uri
		if(strpos($uri, "?") >0){
			$uri = substr($uri,0,strpos($uri, "?"));
		}
		//add slash to the end of uri if there isnt one	
		if($uri[strlen($uri)-1] != "/"){
			$uri .= "/";
		}
		$this->uriArray = explode("/", substr($uri,1));		
	}
	
	/**
	 * get Module name	
	 */
	public function getModule(){
		if($this->hasModdule()){			
			if($this->uriArray[$this->moduleIndex] !== ""){
				return $this->uriArray[$this->moduleIndex];
			}else{
				return $this->defaultModule;
			}
		}else {
			return null;
		}
	}

	/**
	 * getController
	 *
	 */
	public function getController(){		
		if(!is_null($this->getModule())){
			//module exists and controller exists and not empty string
			if($this->hasController() && $this->uriArray[$this->controllerIndex] != ""){
				return ucfirst($this->uriArray[$this->controllerIndex]).$this->controllerPostfix;
			}else{
				//default controller under module/controller/action convention
				return "Index".$this->controllerPostfix;
			} 			
		}else {
			return null;
		}
	}

	/**
	 * get action name
	 * Enter description here ...
	 */
	public function getAction(){		
		if(!is_null($this->getModule())){
			//module exist and action exist and not empty string
			if($this->hasAction() && $this->uriArray[$this->actionIndex] != ""){				
				return $this->actionPrefix.ucfirst($this->uriArray[$this->actionIndex]);				
			}else{
				return $this->actionPrefix."Index";
			}
		}else{
			return null;
		}
	}

	/**
	 * do a test if modulename, controllername
	 * and actionname are all valid
	 */
	public function validateController(){
		//null test
		if(is_null($this->getModule()) || is_null($this->getController())
									 || is_null($this->getAction()))
		{
			return false;
		}		
		//path to controller file
		if($this->isFromAdmin){
			$this->controllerFile = APPLICATION_PATH."/admins/".$this->getModule()."/controller/"
							  .$this->getController().".php";
		}else{
			$this->controllerFile = APPLICATION_PATH."/module/".$this->getModule()."/controller/"
							  .$this->getController().".php";
		}
		//file exist test
		if(file_exists($this->controllerFile)){	
//			require_once 'snc-core/AbstractController.php';	
                        $fileContent  = file_get_contents($this->controllerFile);
                        if(strpos($fileContent,  $this->getAction())){
                            return true;
                        }else {
                            return false;
                        }
//			include_once $this->controllerFile;
//			$methods = get_class_methods($this->getController());
//			foreach($methods as $name) {
//				if($name == $this->getAction()){
//					return true;
//				}
//			}			
		}else{
			return false;
		}		
	}
	
	/**
	 * test that view file exist
	 * Enter description here ...
	 */
	public function validateView(){
		if($this->validateController()){
			//path to view file: example modulename/view/Index/Index.phtml
			if($this->isFromAdmin){
				$this->viewFile = APPLICATION_PATH."/admins/".$this->getModule()."/view/"
								  .str_replace($this->controllerPostfix,"",$this->getController())."/"
								  .str_replace($this->actionPrefix,"", $this->getAction()).".phtml";
			}else{
				$this->viewFile = APPLICATION_PATH."/module/".$this->getModule()."/view/"
								  .str_replace($this->controllerPostfix,"",$this->getController())."/"
								  .str_replace($this->actionPrefix,"", $this->getAction()).".phtml";
			}
			//file existe ?
			if(file_exists($this->viewFile)){
				return true;	
			}else{
				return false;
			}
		}else{
			return false;
		}
	}
	
	/**
	 * test that controller and view exist for the given uri
	 * @return controllerfile, viewfile, and Action or null
         * name of Class of controller will be : modulenameNameController. example: LoginIndex
	 */
	public function validate(){
		if($this->validateController()&& $this->validateView()){
			$dispatcher = array("controller"=>array("path"=>$this->controllerFile,
							"name"=>  str_replace($this->controllerPostfix,"",ucfirst($this->getModule()).$this->getController())),
							    "view"=>$this->viewFile,
								"action"=>$this->getAction());
			return $dispatcher;
		}else{
			return null;
		}
	}
	
	/**
	 * test that module not null 
	 */
	public function hasModdule(){
		if(count($this->uriArray)>0){
			if($this->uriArray[0] == "admin"){
				$this->moduleIndex = 1;
				$this->controllerIndex = 2;
				$this->actionIndex = 3; 
				$this->isFromAdmin = true;
				return (count($this->uriArray)>1); // example : admin/module1		
			}else{
				return true; //example: module1
			}
		}else {
			return false; //example : "/"
		}		
	}
	
	/**
	 * test that controller not null	
	 */
	public function hasController(){
		if($this->hasModdule()){
			if($this->isFromAdmin){
				return count($this->uriArray)>2;
			}else{
				return count($this->uriArray)>1;
			}
		}else{
			return false;
		}
	}
	
	/**
	 * test that action not null	 
	 */
	public function hasAction(){
		if($this->hasModdule()){
			if($this->isFromAdmin){
				return count($this->uriArray)>3;
			}else{
				return count($this->uriArray)>2;
			}
		}else{
			return false;
		}
	}
	
	/**
	 * get controller file
	 * 
	 */
	public function getControllerFile(){
		return $this->controllerFile;
	}
	
	/**
	 * get view File
	 * 
	 */
	public function getViewFile(){
		return $this->viewFile;
	}
	
	/**
	 * pre-condition: this method will return valid value after 
	 * validate() has been called.
	 * Enter description here ...
	 */
	public function isAdmin(){
		return $this->isFromAdmin;
	}
}
?>